package iot.jtt808;

import iot.utils.DataPackUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by dave on 18-7-15 下午9:41.
 */
public class DataPack<T> implements Encoder {
    public static final byte success = 0;
    public static final byte failure = 1;
    public static final byte msg_error = 2;
    public static final byte unsupported = 3;
    public static final byte warnning_msg_ack = 4;

    private int msgId;          // 消息ID，命令字
    private boolean encrypted;  // 是否RSA加密
    private boolean split;      // 是否分包
    private String sim;         // sim卡号
    private int sequenceNo;     // 流水号
    private int contentSize;    // 消息体长度
    private int packageCount;   // 分包后的包数，未分包时为0
    private int packageNo;      // 包序号，示分包时为0
    private byte checksum;      // 校验码
    private T body;

    // 下发类消息编码
    public byte[] encode() {
        byte[] bb = new byte[0];
        if (body instanceof Encoder) {
            bb = ((Encoder) body).encode();
        }

        List<Byte> bytes = new ArrayList<>(50 + bb.length);
        bytes.addAll(DataPackUtil.getWordBytes(msgId));         // 消息ID
        bytes.addAll(DataPackUtil.getWordBytes(bb.length));     // 消息包封装项，这里假定不分包，数据不加密
        bytes.addAll(DataPackUtil.getBCDBytes(sim));            // 手机号
        bytes.addAll(DataPackUtil.getWordBytes(sequenceNo));    // 流水号
        // 消息体
        for (byte b : bb) {
            bytes.add(b);
        }
        bytes.add(DataPackUtil.checksum(bytes, 0, bytes.size())); // 校验位

        // 转义
        List<Byte> escaped = new ArrayList<>(bytes.size() + 50);
        escaped.add((byte) 0x7E); //标识位(0x7E)
        for (Byte b : bytes) {
            if (0x7D == (b & 0xFF)) {
                // 0x7D->0x7D0x01
                escaped.add((byte) 0x7D);
                escaped.add((byte) 0x01);
            } else if (0x7E == (b & 0xFF)) {
                // 0x7E->0x7D0x02
                escaped.add((byte) 0x7D);
                escaped.add((byte) 0x02);
            } else {
                escaped.add(b);
            }
        }

        escaped.add((byte) 0x7E); //标识位(0x7E)
        return DataPackUtil.byteListToArray(escaped);
    }

    public int getMsgId() {
        return msgId;
    }

    public void setMsgId(int msgId) {
        this.msgId = msgId;
    }

    public boolean isEncrypted() {
        return encrypted;
    }

    public void setEncrypted(boolean encrypted) {
        this.encrypted = encrypted;
    }

    public boolean isSplit() {
        return split;
    }

    public void setSplit(boolean split) {
        this.split = split;
    }

    public String getSim() {
        return sim;
    }

    public void setSim(String sim) {
        this.sim = sim;
    }

    public int getSequenceNo() {
        return sequenceNo;
    }

    public void setSequenceNo(int sequenceNo) {
        this.sequenceNo = sequenceNo;
    }

    public int getContentSize() {
        return contentSize;
    }

    public void setContentSize(int contentSize) {
        this.contentSize = contentSize;
    }

    public int getPackageCount() {
        return packageCount;
    }

    public void setPackageCount(int packageCount) {
        this.packageCount = packageCount;
    }

    public int getPackageNo() {
        return packageNo;
    }

    public void setPackageNo(int packageNo) {
        this.packageNo = packageNo;
    }

    public byte getChecksum() {
        return checksum;
    }

    public void setChecksum(byte checksum) {
        this.checksum = checksum;
    }

    public T getBody() {
        return body;
    }

    public void setBody(T body) {
        this.body = body;
    }
}
